package com.town.garden.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.town.garden.chain.AbstractServerStartHandler;
import com.town.garden.constant.GlobalConstant;
import com.town.garden.entiy.ChannelInfo;
import com.town.garden.entiy.MediaServerItem;
import com.town.garden.entiy.StreamInfo;
import com.town.garden.entiy.StreamRequest;
import com.town.garden.entiy.response.ZlKResponse;
import com.town.garden.enums.DeviceStatusEnum;
import com.town.garden.enums.ZLMediaKitEnum;
import com.town.garden.propertites.NvrProperties;
import com.town.garden.service.ZLMediaKitService;
import com.town.garden.storage.NvrSessionStorage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.lang.management.GarbageCollectorMXBean;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description
 * @E-mail cwm3412638@163.com
 * @Author cwm
 * @Date 2022/5/17
 */
@Service(ZLMediaKitServiceImpl.BEAN_NAME)
@Slf4j
public class ZLMediaKitServiceImpl extends AbstractServerStartHandler implements ZLMediaKitService {
    public static final String BEAN_NAME = "zLMediaKitServiceImpl";
    @Autowired
    private NvrProperties nvrProperties;
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 下一个责任链对象
     * {@linkplain NvrAlarmEventServiceImpl}
     */
    @Autowired
    @Qualifier(NvrAlarmEventServiceImpl.BEAN_NAME)
    private AbstractServerStartHandler abstractServerStartHandler;

    private static final Map<String, StreamRequest> STREAM = new ConcurrentHashMap<>();

    @Override
    public void addStreamProxy(StreamRequest streamRequest) {
        final String url = GlobalConstant.HTTP_PREFIX + nvrProperties.getZlmediakitIp() + ZLMediaKitEnum.ADD_STREAM_PROXY.getUrl();
        final HttpEntity<?> entity = new HttpEntity<>(JSONUtil.parse(streamRequest));
        ResponseEntity<ZlKResponse> exchange = restTemplate.exchange(url, HttpMethod.POST, entity, ZlKResponse.class);
        if (HttpStatus.OK.value() == exchange.getStatusCodeValue() && Objects.requireNonNull(exchange.getBody()).getCode() == 0) {
            STREAM.put(streamRequest.getApp(), streamRequest);
        }
    }

    /**
     * 获取所有代理流媒体服务url
     *
     * @return
     */
    @Override
    public List<StreamInfo> getMediaList() {
        List<StreamInfo> streamInfos = new ArrayList<>();
        for (String key : STREAM.keySet()
        ) {
            final StreamRequest streamRequest = STREAM.get(key);
            final String stream = streamRequest.getStream();
            final String app = streamRequest.getApp();
            StreamInfo streamInfoResult = new StreamInfo();
            streamInfoResult.setStream(stream);
            streamInfoResult.setApp(app);
            streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s", nvrProperties.getZlmediakitIp(), MediaServerItem.rtmpPort, app, stream));
            if (MediaServerItem.rtmpSSlPort != 0) {
                streamInfoResult.setRtmps(String.format("rtmps://%s:%s/%s/%s", nvrProperties.getZlmediakitIp(), MediaServerItem.rtmpSSlPort, app, stream));
            }
            streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s", nvrProperties.getZlmediakitIp(), MediaServerItem.rtspPort, app, stream));
            if (MediaServerItem.rtspSSLPort != 0) {
                streamInfoResult.setRtsps(String.format("rtsps://%s:%s/%s/%s", nvrProperties.getZlmediakitIp(), MediaServerItem.rtspSSLPort, app, stream));
            }
            streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.live.flv", nvrProperties.getZlmediakitIp(), MediaServerItem.httpPort, app, stream));
            streamInfoResult.setWs_flv(String.format("ws://%s:%s/%s/%s.live.flv", nvrProperties.getZlmediakitIp(), MediaServerItem.httpPort, app, stream));
            streamInfoResult.setHls(String.format("http://%s:%s/%s/%s/hls.m3u8", nvrProperties.getZlmediakitIp(), MediaServerItem.httpPort, app, stream));
            streamInfoResult.setWs_hls(String.format("ws://%s:%s/%s/%s/hls.m3u8", nvrProperties.getZlmediakitIp(), MediaServerItem.httpPort, app, stream));
            streamInfoResult.setFmp4(String.format("http://%s:%s/%s/%s.live.mp4", nvrProperties.getZlmediakitIp(), MediaServerItem.httpPort, app, stream));
            streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4", nvrProperties.getZlmediakitIp(), MediaServerItem.httpPort, app, stream));
            streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts", nvrProperties.getZlmediakitIp(), MediaServerItem.httpPort, app, stream));
            streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts", nvrProperties.getZlmediakitIp(), MediaServerItem.httpPort, app, stream));
            if (MediaServerItem.httpSSlPort != 0) {
                streamInfoResult.setHttps_flv(String.format("https://%s:%s/%s/%s.live.flv", nvrProperties.getZlmediakitIp(), MediaServerItem.httpSSlPort, app, stream));
                streamInfoResult.setWss_flv(String.format("wss://%s:%s/%s/%s.live.flv", nvrProperties.getZlmediakitIp(), MediaServerItem.httpSSlPort, app, stream));
                streamInfoResult.setHttps_hls(String.format("https://%s:%s/%s/%s/hls.m3u8", nvrProperties.getZlmediakitIp(), MediaServerItem.httpSSlPort, app, stream));
                streamInfoResult.setWss_hls(String.format("wss://%s:%s/%s/%s/hls.m3u8", nvrProperties.getZlmediakitIp(), MediaServerItem.httpSSlPort, app, stream));
                streamInfoResult.setHttps_fmp4(String.format("https://%s:%s/%s/%s.live.mp4", nvrProperties.getZlmediakitIp(), MediaServerItem.httpSSlPort, app, stream));
                streamInfoResult.setWss_fmp4(String.format("wss://%s:%s/%s/%s.live.mp4", nvrProperties.getZlmediakitIp(), MediaServerItem.httpSSlPort, app, stream));
                streamInfoResult.setHttps_ts(String.format("https://%s:%s/%s/%s.live.ts", nvrProperties.getZlmediakitIp(), MediaServerItem.httpSSlPort, app, stream));
                streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts", nvrProperties.getZlmediakitIp(), MediaServerItem.httpSSlPort, app, stream));
                streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts", nvrProperties.getZlmediakitIp(), MediaServerItem.httpSSlPort, app, stream));
            }
            streamInfos.add(streamInfoResult);
        }
        return streamInfos;
    }

    /**
     * 获取流媒体服务信息 保存信息
     */
    @Override
    public void getServerConfig() {
        String url = GlobalConstant.HTTP_PREFIX + nvrProperties.getZlmediakitIp() + ZLMediaKitEnum.GET_SERVER_CONFIG.getUrl();
        url = url + "?secret=" + nvrProperties.getZlmediakitSecret();
        try {
            final ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
            if (HttpStatus.OK.value() == exchange.getStatusCodeValue()) {
                final JSONObject jsonObject = JSON.parseObject(exchange.getBody());
                if (jsonObject.getInteger("code") == 0) {
                    JSONArray data = jsonObject.getJSONArray("data");
                    JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class);
                    MediaServerItem.httpPort = Integer.parseInt(mediaJSON.get("http.port").toString());
                    MediaServerItem.httpSSlPort = Integer.parseInt(mediaJSON.get("http.sslport").toString());
                    MediaServerItem.rtmpPort = Integer.parseInt(mediaJSON.get("rtmp.port").toString());
                    MediaServerItem.rtmpSSlPort = Integer.parseInt(mediaJSON.get("rtmp.sslport").toString());
                    MediaServerItem.rtspPort = Integer.parseInt(mediaJSON.get("rtsp.port").toString());
                    MediaServerItem.rtspSSLPort = Integer.parseInt(mediaJSON.get("rtsp.sslport").toString());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void handlerOperation() {
        //获取流媒体服务配置
        getServerConfig();
        //服务启动注册代理
        if (CollectionUtil.isNotEmpty(NvrSessionStorage.CHANNEL_IP_MAP)) {
            for (String key : NvrSessionStorage.CHANNEL_IP_MAP.keySet()
            ) {
                ChannelInfo channelInfo = NvrSessionStorage.CHANNEL_IP_MAP.get(key);
                //说明设备在线注册代理
                if (DeviceStatusEnum.ONLINE.getStatus().equals(channelInfo.getStatus())) {
                    //默认播放Url规则 ：rtsp://admin:HuaWei123@192.168.120.7/LiveMedia/ch1/Media1
                    final String rtspUrl = String.format("rtsp://%s:%s@%s/LiveMedia/ch1/Media1",
                            nvrProperties.getCameraDefaultAccount(),
                            nvrProperties.getCameraDefaultPassword(), channelInfo.getIpAddress());
                    final StreamRequest streamRequest = new StreamRequest();
                    streamRequest.setStream(key);
                    streamRequest.setApp(key);
                    streamRequest.setIp(channelInfo.getIpAddress());
                    streamRequest.setUrl(rtspUrl);
                    streamRequest.setSecret(nvrProperties.getZlmediakitSecret());
                    streamRequest.setRtp_type(1);
                    streamRequest.setEnable_mp4(false);
                    addStreamProxy(streamRequest);
                }
            }
        }
        //调用下一个责任链
        abstractServerStartHandler.handlerOperation();
    }

}
